import type { App } from 'vue'
import axios, { type ResponseType } from 'axios'
import qs from 'qs'
import { ElMessage } from 'element-plus'
import i18n from '@/utils/i18n/i18n'

// axios.defaults.timeout = 150000
// axios.defaults.baseURL = import.meta.env.VITE_SERVE + import.meta.env.VITE_APP_BASE_API
const request = axios.create({
  baseURL: import.meta.env.VITE_SERVE + import.meta.env.VITE_APP_BASE_API,
  timeout: 150000
})

// 设置请求拦截器
request.interceptors.request.use(
  config => {
    const systemKey = localStorage.getItem('systemKey')
    systemKey && (config.headers.systemKey = systemKey)
    // nprogress.start()
    if (config.method === 'get') {
      config.data = { unused: 0 } // 这个是关键点，加入这行就可以了  解决get  请求添加不上content_type
      // 设置get请求,不设置的话，url的一些特殊字符传输的时候会报错
      let url = config.url || ''
      // get参数编码
      if (config.method === 'get' && config.params) {
        url += '?'
        const keys = Object.keys(config.params)
        for (const key of keys) {
          url += `${key}=${encodeURI(config.params[key])}&`
        }
        url = url.substring(0, url.length - 1)
        config.params = {}
      }
      config.url = url
    }

    // 检查请求数据中是否包含文件，并验证文件大小
    if (config.data instanceof FormData) {
      for (let [key, value] of config.data.entries()) {
        if (value instanceof File) {
          if (value.size > 10 * 1024 * 1024) {
            // 10MB 10 * 1024 * 1024
            // 文件大小超过限制，终止请求
            // nprogress.done();
            //超过上传文件大小限制
            return Promise.reject(new Error(i18n.global.t('l.http00000'))) // 文件过大，请重新上传
          }
        }
      }
    }
    return config
  },
  error => {
    return Promise.reject(error)
  }
)

// 响应拦截器
request.interceptors.response.use(
  response => {
    if (['', '200', 200, null, undefined, 500, '500'].includes(response.data.code)) {
      return Promise.resolve(response.data)
    } else {
      if (response.data.code) {
        let str = ''
        switch (response.data.code) {
          // 401: 登录失效
          // 未登录则跳转登录页面，并携带当前页面的路径
          // 在登录成功后返回当前页面，这一步需要在登录页操作。
          case 401:
          case '401':
            str = i18n.global.t('l.http00001') // 登录失效
            // setTimeout(() => {
            //   router.replace({ path: '/', query: { redirect: router.currentRoute.fullPath }})
            // }, 500)
            break
          // 403 权限不足
          case 403:
          case '403':
            str = i18n.global.t('l.http00002') // 权限不足
            break
          // 404请求资源不存在
          case 404:
          case '404':
            str = i18n.global.t('l.http00003') // 404请求资源不存在
            break
          // 其他错误，直接抛出错误提示
          default:
            str = response.data.message
        }
        ElMessage.error(str)
      }
      return Promise.reject(response)
    }
  },
  error => {
    // nprogress.done()
    let str = ''
    switch (error.message) {
      // 服务器无法连接
      case 'Network Error':
        str = i18n.global.t('l.http00004') // 服务器无法连接
        break
      // 404请求资源不存在
      case 'Request failed with status code 404':
        str = i18n.global.t('l.http00005') // 404请求资源不存在
        break
      // 其他错误
      default:
        str = error.message
    }
    ElMessage.error(str)
    return Promise.reject(error)
  }
)

/**
 * get方法，对应get请求
 * @param {String} url [请求的url地址]
 * @param {Object} params [请求时携带的参数]
 */
function get(url: string, params?: object, headers?: any, responseType?: ResponseType): Promise<any> {
  headers = headers || {}
  return new Promise((resolve, reject) => {
    request
      .get(url, {
        params: params,
        headers: headers,
        responseType: responseType || 'json' // 表明返回服务器响应的数据类型
      })
      .then(res => {
        resolve(res.data)
      })
      .catch(err => {
        reject(err)
      })
  })
}

/**
 * post方法，对应post请求
 * @param {String} url [请求的url地址]
 * @param {Object} data [请求时携带的参数]
 */
function post(url: string, data?: object, headers?: any, responseType?: ResponseType): Promise<any> {
  headers = headers || {}
  return new Promise((resolve, reject) => {
    request
      .post(
        url,
        qs.stringify(data, {
          arrayFormat: 'repeat',
          skipNulls: true, // 跳过 null 值
          allowDots: true
        }),
        {
          headers: headers,
          responseType: responseType || 'json' // 表明返回服务器响应的数据类型
        }
      )
      .then(res => {
        resolve(res.data)
      })
      .catch(err => {
        // if (err.message == 'Network Error') {
        //     common.notify('error', '服务器无法连接')
        // }

        reject(err)
      })
  })
}

function jsonPost(url: string, data?: object, headers?: any, responseType?: ResponseType): Promise<any> {
  if ([undefined, null].includes(headers)) {
    headers = { 'Content-Type': 'application/json;charset=utf-8' }
  } else {
    headers['Content-Type'] = 'application/json;charset=utf-8'
  }
  return new Promise((resolve, reject) => {
    request
      .post(url, data, {
        headers: headers,
        responseType: responseType || 'json' // 表明返回服务器响应的数据类型
      })
      .then(res => {
        resolve(res.data)
      })
      .catch(err => {
        // if (err.message == 'Network Error') {
        //     common.notify('error', '服务器无法连接')
        // }
        reject(err)
      })
  })
}

function uploadFile(url: string, fileData: FormData, headers?: any, responseType?: ResponseType): Promise<any> {
  return new Promise((resolve, reject) => {
    request
      .post(url, fileData, {
        headers: headers || {
          'Content-Type': 'multipart/form-data;boundary=10'
        },
        responseType: responseType || 'json'
      })
      .then(res => {
        resolve(res.data)
      })
      .catch(err => {
        // 这里可以添加特定的错误处理逻辑，比如通知用户
        reject(err)
      })
  })
}

const http: Http = { get, post, jsonPost, uploadFile }

export function setupAxios(app: App) {
  // 注册 axios
  app.config.globalProperties.$http = http
}

export interface Http {
  get: (url: string, params?: object, headers?: any, responseType?: ResponseType) => Promise<any>
  post: (url: string, data?: object, headers?: any, responseType?: ResponseType) => Promise<any>
  jsonPost: (url: string, data?: object, headers?: any, responseType?: ResponseType) => Promise<any>
  uploadFile: (url: string, fileData: FormData, headers?: any, responseType?: ResponseType) => Promise<any>
}

export default request
export { http }
